// Header Protection
#ifndef _RENDERNODE_H_
#define _RENDERNODE_H_

// Include Files
#include "Systems\SystemNode.h"

///* TODO
// * after I am done changing to pre-loading all assets, all "fixing up" by string 
// * searching for named assets in their managers is happening every frame. I should 
// * change this to find them when they are loaded instead.
// */

//// Forward Declarations
//
//// managers
//class CTextureManager;
//class CShaderManager;
//class CMeshManager;
//
//enum param_e
//{
//	PARAM_MAT_MODELVIEW, 
//	PARAM_MAT_MODELVIEWPROJ, 
//	PARAM_MAT_MODELVIEW_ROT, 
//	PARAM_MAT_MODELVIEWPROJ_ROT, 
//};

// Namespace
namespace IE
{
	/////////////////////////////////////////////////////////////////////////////////
	// A node to hold the render data for an object in a thread safe manner.
	class CRenderNode : public ABCSystemNode
	{
		//private:    // structures
		//	// TODO: TTexParam, TMatParam, w/e other params there are
		//	struct TTexture
		//	{
		//		string_t strName;
		//		string_t strParam;
		//	};
		//
		//	struct TMatrix
		//	{
		//		string_t strParam;
		//		param_e  eType;
		//	};

	public:     // methods

		//// TODO: it will obviously be a problem to have to overload new in every 
		////     dynamically allocated class which uses a vector or matrix, I will have to 
		////     do something about this for sure... 
		//// TEMP: overloading new in every dynamically allocated class that uses __m128
		//// LATER: overload new globally to take in an alignment
		//// AWESOME: memory manager automatically knows to align it
		//void *operator new( size_t _uiBytes )
		//{
		//	// allocate memory with some extra
		//	byte_t *pUnaligned = (byte_t *)malloc( _uiBytes + 16 );

		//	// move the pointer over at least one and align it
		//	byte_t *pAligned = pUnaligned + (16 - uint_t(pUnaligned) % 16);

		//	// add the offset into the previous byte
		//	pAligned[-1] = byte_t(pAligned - pUnaligned);

		//	// return the aligned memory
		//	return pAligned;
		//}

		//void operator delete(void *pAligned)
		//{
		//	// find the amount this pointer was offset for alignment
		//	byte_t uiOffset = ((byte_t *)pAligned)[-1];

		//	// move the pointer
		//	byte_t *pUnaligned = (byte_t *)pAligned - uiOffset;

		//	// free the memory
		//	free(pUnaligned);
		//}

		CRenderNode();
		virtual ~CRenderNode() { }

		//void Lock()   { m_Mutex.Lock(); }
		//void Unlock() { m_Mutex.Unlock(); }

		//void Render( matrix_t const &_matView, matrix_t const &_matProj );

		//matrix_t GetTransform()
		//{
		//	return m_matTransform;
		//}

		//void SetTransform( matrix_t const &_matTransform )
		//{
		//	m_matTransform = _matTransform;
		//}

		//void SetMatrixParam( string_t _strParam, param_e _eParam )
		//{
		//	// create the matrix param
		//	TMatrix mat;
		//	mat.strParam = _strParam;
		//	mat.eType    = _eParam;
		//	m_lstMatParams.Append(mat);
		//}

		//void AddTexParam( string_t _strName, string_t _strParam )
		//{
		//	// create the texture param
		//	TTexture tex;
		//	tex.strName  = _strName;
		//	tex.strParam = _strParam;
		//	m_lstTexParams.Append(tex);
		//}

		//void SetShader( string_t _strShader )
		//{
		//	m_strShader = _strShader;
		//}

		//void SetMesh( string_t _strMesh )
		//{
		//	m_strMesh = _strMesh;
		//}

		//string_t GetShaderName() { return m_strShader; }

		//private:
		//	// managers
		//	CSingleton<CTextureManager> m_pTextureManager;
		//	CSingleton<CShaderManager>  m_pShaderManager;
		//	CSingleton<CMeshManager>    m_pMeshManager;
		//
		//	mutex_t  m_Mutex;
		//	matrix_t m_matTransform;
		//
		//	// mesh
		//	string_t m_strMesh;
		//
		//	// shader
		//	string_t m_strShader;
		//
		//	list_t<TTexture> m_lstTexParams;
		//	list_t<TMatrix>  m_lstMatParams;

	private:    // dummy definitions
		CRenderNode( CRenderNode const & );
		CRenderNode &operator =( CRenderNode const & );
	};

	//class CRenderStateEventArg : public CEventArg
	//{
	//public:     // methods
	//
	//	CRenderStateEventArg(CRenderState *_pRenderState) : 
	//			CEventArg(), m_pRenderState(_pRenderState)
	//			{
	//				m_pRenderState->AddRef();
	//			}
	//
	//			virtual ~CRenderStateEventArg()
	//			{
	//				m_pRenderState->Release();
	//			}
	//
	//			CRenderState *GetRenderState() { return m_pRenderState; }
	//
	//private:    // data
	//	CRenderState *m_pRenderState;
	//
	//private:    // dummy definitions
	//	CRenderStateEventArg( CRenderStateEventArg const & );
	//	CRenderStateEventArg &operator =( CRenderStateEventArg const & );
	//};
}

// Header Protection
#endif // _RENDERNODE_H_

// RenderNode.cpp
///////////////////////////////////////////////////////////////////////////////////////
//// Include Files
//#include "Render\RenderState.h"
//
//// managers
//#include "Managers\TextureManager.h"
//#include "Managers\ShaderManager.h"
//#include "Managers\MeshManager.h"
//
//// shaders
//#include "Main\GLExt.h"
//#include "Cg\CgGL.h"
//
///////////////////////////////////////////////////////////////////////////////////////
//// CRenderState Implementation
//CRenderState::CRenderState() : 
//	m_Mutex(), 
//	m_matTransform(), 
//	m_strMesh(), 
//	m_strShader(), 
//	m_lstMatParams(), 
//	m_lstTexParams(), 
//	m_uRefCount(0)
//{ }
//
//void CRenderState::Render( matrix_t const &_matView, matrix_t const &_matProj )
//{
//#pragma warning(disable:981)
//
//	// HACK: transform is currently the only element which changes
//	Lock();
//	matrix_t matModelView = MatrixMul(m_matTransform, _matView);
//	Unlock();
//
//	matrix_t matModelViewProj = MatrixMul(matModelView, _matProj);
//
//	matrix_t matModelViewRot = matModelView;
//	matModelViewRot.row[3] = Vector(0.0f, 0.0f, 0.0f, 1.0f);
//
//	matrix_t matModelViewProjRot = MatrixMul(matModelViewRot, _matProj);
//
//	// get the technique
//	CGtechnique tech = (CGtechnique)m_pShaderManager->GetTechnique(m_strShader);
//	assert(tech);
//
//	// set the matrix parameters
//	for( uint_t i = 0; i < m_lstMatParams.GetSize(); ++i )
//	{
//#ifdef _DEBUG
//		GLenum eError;
//#endif
//
//		CGparameter param = (CGparameter)m_pShaderManager->GetParameter(m_strShader, m_lstMatParams[i].strParam);
//		assert(param);
//
//#ifdef _DEBUG
//		eError = glGetError();
//		assert(eError == GL_NO_ERROR);
//#endif
//
//		switch(m_lstMatParams[i].eType)
//		{
//
//		case PARAM_MAT_MODELVIEW:
//			cgGLSetMatrixParameterfr(param, matModelView.arr);
//			break;
//
//		case PARAM_MAT_MODELVIEWPROJ:
//			cgGLSetMatrixParameterfr(param, matModelViewProj.arr);
//			break;
//
//		case PARAM_MAT_MODELVIEW_ROT:
//			cgGLSetMatrixParameterfr(param, matModelViewRot.arr);
//			break;
//
//		case PARAM_MAT_MODELVIEWPROJ_ROT:
//			cgGLSetMatrixParameterfr(param, matModelViewProjRot.arr);
//			break;
//
//		}
//
//#ifdef _DEBUG
//		eError = glGetError();
//		assert(eError == GL_NO_ERROR);
//#endif
//	}
//
//	// set texture parameters
//	for( uint_t iTex = 0; iTex < m_lstTexParams.GetSize(); ++iTex )
//	{
//		TTexture    *pTex   = &m_lstTexParams[iTex];
//
//		CGparameter TexParam = (CGparameter)m_pShaderManager->GetParameter(m_strShader, pTex->strParam);
//		uint_t      uiTex    = m_pTextureManager->GetTexture(pTex->strName);
//
//		cgGLSetupSampler(TexParam, uiTex);
//	}
//
//	// get the mesh from the mesh manager
//	TMesh *pMesh = m_pMeshManager->GetMesh(m_strMesh);
//
//	// bind the vertex array object
//	glBindVertexArray(pMesh->uiVAO);
//
//	GLenum eError = glGetError();
//	if( eError != GL_NO_ERROR )
//	{
//		assert(CE_FALSE);
//		// TODO: check error code
//	}
//
//	// loop through passes
//	CGpass pass = cgGetFirstPass(tech);
//	while(pass)
//	{
//		cgSetPassState(pass);
//
//		// draw the mesh
//		glDrawElements(GL_TRIANGLES, pMesh->uiIndexCount,
//			pMesh->eIndexType, (void *)0 );
//
//		cgResetPassState(pass);
//		pass = cgGetNextPass(pass);
//	}
//
//	eError = glGetError();
//	if( eError != GL_NO_ERROR )
//	{
//		assert(CE_FALSE);
//		// TODO: check error code
//	}
//
//#pragma warning(default:981)
//}
